package icu.zhhll.util.qrcode;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 二维码工具类
 *
 * @author zh
 * @date 2023/9/18 16:47
 * @see <a href="https://www.cnblogs.com/codingcc1/p/11099788.html>https://www.cnblogs.com/codingcc1/p/11099788.html</a>
 */
public class QrCodeUtils {


    /**
     * 二维码内容解析
     *
     * @param qrCodePath 二维码文件路径
     * @return
     */
    public static String decodeQrCode(String qrCodePath) {
        File file = new File(qrCodePath);
        if (!file.exists())
            throw new RuntimeException("文件不存在");
        //file->内存中的一张图片
        BufferedImage image;
        try {
            image = ImageIO.read(file);
            MultiFormatReader formatReader = new MultiFormatReader();
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            //图片 ->result
            Map<DecodeHintType, String> map = new HashMap<>();
            map.put(DecodeHintType.CHARACTER_SET, "utf-8");
            Result result = formatReader.decode(binaryBitmap, map);
            System.out.println("解析结果：" + result.toString());
            return result.toString();
        } catch (IOException | NotFoundException e) {
            throw new RuntimeException("解析失败");
        }
    }

    /**
     * 生成二维码带图片
     *
     * @param qrCodePath 二维码存放路径
     * @param format     图片格式(png、jpg)
     * @param content    二维码内容
     * @param width      宽
     * @param height     高
     * @param logo       图片内容
     * @throws Exception
     */
    public static void generateWithImg(String qrCodePath, String format, String content,
                                       int width, int height, String logo) throws Exception {
        BufferedImage image = baseQrCodeImage(content, width, height);
        //画logo
        insertImage(image, logo);
        //string->file
        File file = new File(qrCodePath);
        //生成图片
        ImageIO.write(image, format, file);

    }

    /**
     * 生成二维码
     *
     * @param qrCodePath 二维码存放路径
     * @param format     图片格式(png、jpg)
     * @param content    二维码内容
     * @param width      宽
     * @param height     高
     * @throws Exception
     */
    public static void generate(String qrCodePath, String format, String content,
                                int width, int height) throws Exception {
        BufferedImage image = baseQrCodeImage(content, width, height);

        //string->file
        File file = new File(qrCodePath);
        //生成图片
        ImageIO.write(image, format, file);

    }

    /**
     * 基础二维码图片
     *
     * @param content 内容
     * @param width   宽
     * @param height  高
     * @return
     * @throws WriterException
     */
    private static BufferedImage baseQrCodeImage(String content, int width, int height) throws WriterException {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        //排错率  L<M<Q<H
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //编码
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        //外边距：margin
        hints.put(EncodeHintType.MARGIN, 1);
        /*
         * content : 需要加密的 文字
         * BarcodeFormat.QR_CODE:要解析的类型（二维码）
         * hints：加密涉及的一些参数：编码、排错率
         */
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
        //内存中的一张图片：此时需要的图片 是二维码-> 需要一个boolean[][] ->BitMatrix
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, (bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF));
            }
        }
        return image;
    }

    //传入logo、二维码 ->带logo的二维码
    public static BufferedImage insertImage(BufferedImage matrixImage, String logo) throws IOException {

        //画logo： String->BufferedImage(内存)
        BufferedImage logoImg = ImageIO.read(new File(logo));
        int height = matrixImage.getHeight();
        int width = matrixImage.getWidth();


        // 插入LOGO
        Graphics2D graph = matrixImage.createGraphics();

        graph.drawImage(logoImg, width * 2 / 5, height * 2 / 5, width / 5, height / 5, null);

        //产生一个 画 白色圆角正方形的 画笔
        BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //将画板-画笔 关联
        graph.setStroke(stroke);
        //创建一个正方形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(width * 2 / 5, height * 2 / 5, width * 1 / 5, height * 1 / 5,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        graph.setColor(Color.WHITE);
        graph.draw(round);

        //灰色边框
        BasicStroke stroke2 = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        graph.setStroke(stroke2);
        //创建一个正方形
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(width * 2 / 5 + 2, height * 2 / 5 + 2, width * 1 / 5 - 4,
                height * 1 / 5 - 4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        //        Color color = new Color(128,128,128) ;
        graph.setColor(Color.GRAY);
        graph.draw(round2);

        graph.dispose();
        matrixImage.flush();

        return matrixImage;
    }
}
